package com.gin.no_gay_alliance.manager;

import android.util.Log;

import androidx.annotation.NonNull;

import com.gin.common.utils.FileIoUtils;
import com.gin.common.utils.StrUtils;
import com.gin.jackson.utils.JacksonUtils;
import com.gin.jackson.utils.ObjectUtils;
import com.gin.nga.callback.JsonCallback;
import com.gin.nga.exception.NgaException;
import com.gin.nga.method.NukeApi;
import com.gin.nga.response.body.nuke.BlockDataBody;
import com.gin.nga.response.field.BlockData;
import com.gin.no_gay_alliance.app.MyApplication;
import com.gin.no_gay_alliance.callback.Callback;
import com.gin.no_gay_alliance.callback.RequestCallback;
import com.gin.no_gay_alliance.viewmodel.ReplyItem;
import com.gin.no_gay_alliance.viewmodel.TopicItem;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;

/**
 * 屏蔽的用户和关键字管理
 *
 * @author : ginstone
 * @version : v1.0.0
 * @since : 2023/9/12 11:32
 **/
public class BlockDataManager {
    private static final String TAG = BlockDataManager.class.getSimpleName();
    private BlockData blockData;

    /**
     * 清除内存缓存
     */
    public void clear() {
        blockData = null;
    }

    /**
     * 清除文件缓存
     */
    public void clearFile() {
        File cacheFile = getCacheFile(MyApplication.getClient().getUserId());
        if (cacheFile.exists() && cacheFile.delete()) {
            Log.d(TAG, "清除文件缓存");
        }
    }

    /**
     * 拉黑一个用户
     *
     * @param userId 用户id
     */
    public void block(long userId) {
        blockDataList(false, data -> {
            data.getUsers().add(String.valueOf(userId));
            blockDataSet(data, d -> {
            });
        });
    }

    /**
     * 取消拉黑一个用户
     *
     * @param userId 用户id
     */
    public void unblock(long userId) {
        blockDataList(false, data -> {
            data.getUsers().removeIf(i -> i.startsWith(userId + "/"));
            blockDataSet(data, d -> {
            });
        });
    }


    public void blockDataSet(BlockData blockData, @NonNull Callback<BlockData> callback) {
        JacksonUtils.printPretty(blockData);
        this.blockData = null;
        NukeApi.blockDataSet(MyApplication.getClient(), blockData).async(new RequestCallback<>(data -> {
            MyApplication.app.handler.toast(data.getMessage());
            // 删除缓存文件
            long userId = MyApplication.getClient().getUserId();
            File cacheFile = getCacheFile(userId);
            if (cacheFile.exists() && cacheFile.delete()) {
                Log.d(TAG, "删除缓存文件: " + userId);
            }
            // 重新请求
            blockDataList(false, callback);
        }));
    }

    public void blockDataList(boolean ignoreCache, @NonNull Callback<BlockData> callback) {
        if (ignoreCache) {
            clear();
            clearFile();
        }
        if (blockData != null) {
            callback.onSuccess(blockData);
            return;
        }

        File cacheFile = getCacheFile(MyApplication.getClient().getUserId());
        if (cacheFile.exists() && isAvailable(cacheFile)) {
            try {
                BlockData body = FileIoUtils.readObj(cacheFile, BlockData.class);
                blockData = body;
                callback.onSuccess(body);
                return;
            } catch (IOException e) {
                Log.w(TAG, "读取缓存文件错误: " + e.getMessage(), e);
            }
        }
        callback.beforeRequest();
        NukeApi.blockDataList(MyApplication.getClient()).async(new JsonCallback<BlockDataBody>() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                super.onFailure(call, e);
                MyApplication.app.handler.toast(e.getMessage());
                callback.onFailure(call, e);
            }

            @Override
            public void onSuccess(BlockDataBody body) {
                if (ignoreCache) {
                    MyApplication.app.handler.toast("刷新成功");
                }
                BlockData data = body.getData();
                blockData = data;
                try {
                    FileIoUtils.writeObj(cacheFile, data);
                } catch (IOException e) {
                    Log.w(TAG, "写入缓存文件错误: " + e.getMessage(), e);
                }
                callback.onSuccess(data);
            }

            @Override
            public void handleException(NgaException e) {
                super.handleException(e);
                callback.handleException(e);
            }
        });
    }

    /**
     * 判断一个主题是否被屏蔽
     *
     * @param topicItem 主题
     * @return 是否被屏蔽
     */
    public static boolean isBlocked(BlockData data, TopicItem topicItem) {
        String authorId = topicItem.authorId;
        return isBlocked(data, topicItem.title) || (StrUtils.isNumber(authorId) && isBlocked(data, Long.parseLong(authorId)));
    }

    /**
     * 判断一个回复是否被屏蔽
     *
     * @param replyItem 回复
     * @return 是否被屏蔽
     */
    public static boolean isBlocked(BlockData data, ReplyItem replyItem) {
        return isBlocked(data, replyItem.title) || isBlocked(data, replyItem.content) || (replyItem.authorUid != null && isBlocked(data, replyItem.authorUid));
    }


    /**
     * 判断一个字符串是否出现了黑名单中的关键字
     *
     * @param data   屏蔽数据
     * @param string 字符串
     * @return 是否出现屏蔽词
     */
    public static boolean isBlocked(BlockData data, String string) {
        if (data == null || string == null) {
            return false;
        }
        List<String> keywords = data.getKeywords();
        if (ObjectUtils.isEmpty(keywords)) {
            return false;
        }
        for (String keyword : keywords) {
            if (string.contains(keyword)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断一个用户id是否应当被屏蔽
     *
     * @param data   屏蔽数据
     * @param userId 用户id
     * @return 是否被屏蔽
     */
    public static boolean isBlocked(BlockData data, long userId) {
        if (data == null) {
            return false;
        }
        List<String> users = data.getUsers();
        if (ObjectUtils.isEmpty(users)) {
            return false;
        }
        return users.stream().map(s -> s.split("/")[0]).map(Long::parseLong).anyMatch(i -> i == userId);
    }

    /**
     * 缓存文件是否可用
     *
     * @param cacheFile 缓存文件
     * @return 是否可用
     */
    private static boolean isAvailable(@NonNull File cacheFile) {
        // 距离上次修改的时间
        long last = System.currentTimeMillis() - cacheFile.lastModified();
        // 距离修改时间小于1天可用
        return TimeUnit.DAYS.toMillis(1) < last;
    }

    /**
     * 获取缓存文件
     *
     * @param userId 用户id
     * @return 缓存文件
     */
    private static File getCacheFile(long userId) {
        File dir = new File(MyApplication.app.getCacheDir(), "block_data");
        return new File(dir, userId + ".json");
    }

}
